home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / x11 / rpg / crossfir.92 / crossfir / crossfire-0.92.5 / server / spell_util.c < prev    next >
C/C++ Source or Header  |  1996-07-24  |  56KB  |  1,949 lines

  1. /*
  2.  * static char *rcsid_spells_c =
  3.  *   "$Id: spell_util.c,v 1.13 1996/07/24 07:43:21 master Exp master $";
  4.  */
  5.  
  6. /*
  7.     CrossFire, A Multiplayer game for X-windows
  8.  
  9.     Copyright (C) 1994 Mark Wedel
  10.     Copyright (C) 1992 Frank Tore Johansen
  11.  
  12.     This program is free software; you can redistribute it and/or modify
  13.     it under the terms of the GNU General Public License as published by
  14.     the Free Software Foundation; either version 2 of the License, or
  15.     (at your option) any later version.
  16.  
  17.     This program is distributed in the hope that it will be useful,
  18.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  19.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20.     GNU General Public License for more details.
  21.  
  22.     You should have received a copy of the GNU General Public License
  23.     along with this program; if not, write to the Free Software
  24.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  25.  
  26.     The author can be reached via e-mail to master@rahul.net
  27. */
  28.  
  29. #include <global.h>
  30. #include <spells.h>
  31. #include <object.h>
  32. #include <errno.h>
  33. #ifndef __CEXTRACT__
  34. #include <sproto.h>
  35. #endif
  36. #ifdef SOUND_EFFECTS
  37. #include <sounds.h>
  38. #endif
  39. #ifdef sequent
  40. /* stoopid sequent includes don't do this like they should */
  41. extern char * sys_errlist[];
  42. extern int sys_nerr;
  43. #endif
  44.  
  45. char *range_name[range_size] = {
  46.   "none", "bow", "magic", "wand", "rod", "scroll", "horn"
  47. #ifdef ALLOW_SKILLS
  48.     ,"steal"
  49. #endif
  50. };
  51.  
  52. void init_spells() {
  53.   static int init_spells_done = 0;
  54.   int i;
  55.  
  56.   if (init_spells_done)
  57.     return;
  58.   init_spell_param(); /*  peterm:  read the spell parameter file--newspells.c */
  59.   init_spells_done = 1;
  60.   for (i = 0; i < NROFREALSPELLS; i++)
  61.     if (spells[i].archname) {
  62.       if ((spellarch[i] = find_archetype(spells[i].archname)) == NULL)
  63.         LOG(llevError,
  64.             "Spell %s needs arch %s, your archetype file is out of date.\n",
  65.             spells[i].name,spells[i].archname);
  66.     } else
  67.       spellarch[i] = (archetype *) NULL;
  68. #ifdef DUMP_SWITCHES
  69.   if (dump_monsters == 4) {
  70.     for (i = 0; i < NROFREALSPELLS; i++) {
  71.       char *name1 = NULL, *name2 = NULL;
  72.       if (spellarch[i]) {
  73.         name1 = spellarch[i]->name;
  74.  
  75.         if (spellarch[i]->clone.other_arch)
  76.           name2 = spellarch[i]->clone.other_arch->name;
  77.       }
  78.       fprintf(stderr, "%s:%s:%s\n", spells[i].name, name1, 
  79.          (name2?name2:"null"));
  80.     }
  81.     exit(0);
  82.   }
  83. #endif
  84. }
  85.  
  86. void spell_effect(int spell_type, int x, int y, mapstruct *map) {
  87.  
  88.   if (spellarch[spell_type] != (archetype *) NULL) {
  89.     object *effect = arch_to_object(spellarch[spell_type]);
  90.  
  91.     effect->x = x;
  92.     effect->y = y;
  93.  
  94.     insert_ob_in_map(effect, map);
  95.   }
  96. }
  97.  
  98. spell *find_spell(int spelltype) {
  99.   if(spelltype<0||spelltype>NROFREALSPELLS)
  100.     return NULL;
  101.   return &spells[spelltype];
  102. }
  103.  
  104. int path_level_mod(object *op, int sp) {
  105.  spell *s = find_spell(sp);
  106.  int val;
  107.  
  108.  if (op->path_denied & s->path)
  109.   return -100;                /* shouldn't get here, but ... */
  110.  val = ((op->path_repelled & s->path)!=0) * -5 +
  111.     ((op->path_attuned & s->path)!=0) * 5;
  112.  if (op->level - val < 1)
  113.   return op->level-1;
  114.  else
  115.   return val;
  116. }
  117.  
  118. int check_spell_known(object *op,int sp) {
  119.   int i;
  120.   for(i=0; i < (int)op->contr->nrofknownspells; i++)
  121.     if(op->contr->known_spells[i]==sp)
  122.       return 1;
  123.   return 0;
  124. }
  125.  
  126.  
  127. /*
  128.  * cast_spell():
  129.  * Fires spell "type" in direction "dir".
  130.  * If "ability" is true, the spell is the innate ability of a monster.
  131.  * (ie, don't check for blocks_magic(), and don't add AT_MAGIC to attacktype.
  132.  */
  133.  
  134. /* Oct 95 - added cosmetic touches for MULTIPLE_GODS hack -b.t. */
  135.  
  136. int cast_spell(object *op,object *caster,int dir,int type,int ability,SpellTypeFrom item,char *stringarg) {
  137. #ifdef MULTIPLE_GODS
  138.   char *godname;
  139. #endif
  140.   spell *s=find_spell(type);
  141.   int success=0,bonus;
  142.   int duration=SP_PARAMETERS[type].bdur;  /*  get the base duration */
  143.   object casting_object, *orig_op=op;
  144.  
  145. #ifdef MULTIPLE_GODS
  146.   if(!strcmp((godname=determine_god(op)),"none")) godname="Your spirit"; 
  147. #endif
  148.  
  149.   if(item!=spellNormal&&caster!=op) {
  150.     reset_object(&casting_object);
  151.     (void) memcpy((void *)((char *) &casting_object +
  152.         offsetof(object,name)),
  153.                 (void *)((char *) op+offsetof(object,name)),
  154.                 sizeof(object)-offsetof(object, name));
  155.  
  156.     /* Things not cleared by reset_object */
  157.     casting_object.next = NULL;
  158.     casting_object.prev = NULL;
  159.     casting_object.active_next = NULL;
  160.     casting_object.active_prev = NULL;
  161.       /*  these should come from the source object for the spell */
  162.     casting_object.level=caster->level;
  163.     casting_object.path_attuned=caster->path_attuned;
  164.     casting_object.path_repelled=caster->path_repelled;
  165.     casting_object.path_denied=caster->path_denied;
  166.       /* the following must come from the monster/player initiating the spell*/
  167.     casting_object.type=op->type;
  168.     casting_object.env=op->env;
  169.     casting_object.inv=op->inv;
  170.     casting_object.contr=op->contr;
  171.     casting_object.facing=op->facing;
  172.     casting_object.map=op->map;
  173.     set_owner(&casting_object, op);
  174.     casting_object.x=op->x;
  175.     casting_object.y=op->y; 
  176.       /* these are needed for some spells */
  177.     casting_object.stats.luck=op->stats.luck;
  178.     casting_object.stats.Wis=op->stats.Wis;
  179.     casting_object.stats.Cha=op->stats.Cha;
  180.     casting_object.stats.Int=op->stats.Int; 
  181.       /*  set the object */
  182.     op= &casting_object;
  183.   }
  184.  
  185.  
  186.   if(s==NULL) {
  187.     LOG(llevError,"Error, unknown spell: %d\n",type);
  188.     return 0;
  189.   }
  190.  
  191.   if(!(QUERY_FLAG(op, FLAG_WIZ))&&
  192.       (op->type==PLAYER)&&
  193.       (op->contr->shoottype==range_magic)&&
  194.      (item!=spellPotion)&& 
  195.      (!(IS_SUMMON_SPELL(type)&&op->contr->golem!=NULL)))
  196.   {
  197.     if(!spells[type].cleric&& op->stats.sp<SP_level_spellpoint_cost(op,type))
  198.     {
  199.       new_draw_info(NDI_UNIQUE, 0,op,"You don't have enough mana.");
  200.       op->contr->count_left=0;
  201.       return 0;
  202.     }
  203.     if(spells[type].cleric&&op->stats.grace<SP_level_spellpoint_cost(op,type))
  204.     {
  205.       /* it's possible for grace to go negative */
  206.       /* Fine - let grace go negative, but how negative it is should really
  207.        * put a limit on things - in the old method, chance was the same
  208.        * no matter how negative it was.
  209.        *Instead of subtracting 10 from the roll, add in grace (which is
  210.        * negative).  This puts a real limit on things.
  211.        */
  212.       if( (RANDOM()%op->stats.Wis) +op->stats.grace -
  213.           10*SP_level_spellpoint_cost(op,type)/op->stats.maxgrace >0) {
  214. #ifdef MULTIPLE_GODS
  215.               new_draw_info_format(NDI_UNIQUE, 0,op, 
  216.                 "%s grants your prayer, though you are unworthy.",godname);
  217. #else
  218.               new_draw_info(NDI_UNIQUE, 0,op, 
  219.                 "God grants your prayer, though you are unworthy.");
  220. #endif
  221.       }
  222.       else
  223.       {
  224.           prayer_failure(op,op->stats.grace,SP_level_spellpoint_cost(op,type));
  225. #ifdef MULTIPLE_GODS
  226.               new_draw_info_format(NDI_UNIQUE, 0,op,"%s ignores your prayer.",godname);
  227. #else
  228.               new_draw_info(NDI_UNIQUE, 0,op,"God ignores your prayer.");
  229. #endif
  230.           op->contr->count_left=0;
  231.               return 0;
  232.       }
  233.     }
  234.   }
  235.  
  236.   if (op->path_denied & s->path) {
  237.     new_draw_info(NDI_UNIQUE, 0,op, "You are unable to cast that spell.");
  238.     op->contr->count_left=0;
  239.     return RANDOM()%(s->sp)+1;
  240.   }
  241. #ifdef CASTING_TIME
  242.   if (op->casting==-1) /* begin the casting */
  243.    {
  244.      if (item == spellNormal&&!ability){
  245.        op->casting = s->time*PATH_TIME_MULT(op,s);
  246.        op->spell   = s;  /* so no one cast a spell and switchs to get lower 
  247.                 casting times!!! */
  248.        op->spelltype = type;
  249.        op->spell_state = 1;
  250.  
  251.  
  252.     /*  put the stringarg into the object struct so that when the
  253.         spell is actually cast, it knows about the stringarg.
  254.         necessary for the invoke command spells.  */
  255.        if(stringarg) {
  256.           op->spellarg = strdup_local(stringarg);  
  257.     }
  258.     else op->spellarg=NULL;
  259.        return 0;
  260.      }
  261.   } else if (op->casting != 0) {
  262.     if (op->type == PLAYER )
  263.       new_draw_info(NDI_UNIQUE, 0,op,"You are casting!");
  264.     return 0;
  265.   }
  266. #endif
  267.   /*  ban removed on clerical spells in no-magic areas */
  268.   if (!ability && item != spellPotion && 
  269.     ( ((!s->cleric)&&blocks_magic(op->map,op->x,op->y))||
  270.       (( s->cleric)&&blocks_cleric(op->map,op->x,op->y)))) {
  271.     if (op->type!=PLAYER)
  272.       return 0;
  273.     if(s->cleric) 
  274. #ifdef MULTIPLE_GODS
  275.       new_draw_info_format(NDI_UNIQUE, 0,op,"This ground is unholy!  %s ignores you.",godname);
  276. #else
  277.       new_draw_info(NDI_UNIQUE, 0,op,"This ground is unholy!  God ignores you.");
  278. #endif
  279.     else
  280.     switch(op->contr->shoottype) {
  281.     case range_magic:
  282.       new_draw_info(NDI_UNIQUE, 0,op,"Something blocks your spellcasting.");
  283.       break;
  284.     case range_wand:
  285.       new_draw_info(NDI_UNIQUE, 0,op,"Something blocks the magic of your wand.");
  286.       break;
  287.     case range_rod:
  288.       new_draw_info(NDI_UNIQUE, 0,op,"Something blocks the magic of your rod.");
  289.       break;
  290.     case range_horn:
  291.       new_draw_info(NDI_UNIQUE, 0,op,"Something blocks the magic of your horn.");
  292.       break;
  293.     case range_scroll:
  294.       new_draw_info(NDI_UNIQUE, 0,op,"Something blocks the magic of your scroll.");
  295.       break;
  296.     default:
  297.       break;
  298.     }
  299.     return 0;
  300.   }
  301.   if(item == spellNormal && op->type==PLAYER&&s->cleric&&
  302.      RANDOM()%100< s->level*2 - op->level + cleric_chance[op->stats.Wis]-
  303.     op->stats.luck*3) {
  304. #ifdef SOUND_EFFECTS
  305.     play_sound_player_only(op->contr, SOUND_FUMBLE_SPELL);
  306. #endif
  307.     new_draw_info(NDI_UNIQUE, 0,op,"You fumble the spell.");
  308. #ifdef CASTING_TIME
  309.   op->casting = -1;
  310.   op->spell_state = 1;
  311. #endif    
  312.     if(s->sp==0) /* Shouldn't happen... */
  313.       return 0;
  314.     return RANDOM()%(SP_level_spellpoint_cost(op,type)+1)+1;
  315.   }
  316. #ifdef SPELL_ENCUMBRANCE
  317.   if(item == spellNormal && op->type==PLAYER && (!s->cleric) ) {
  318.     int failure = (RANDOM()%200) - op->contr->encumbrance +op->level -s->level +35;
  319.  
  320.     if( failure < 0) {
  321.     new_draw_info(NDI_UNIQUE, 0,op,"You bungle the spell because you have too much heavy equipment in use.");
  322. #ifdef SPELL_FAILURE_EFFECTS
  323.         spell_failure(op,failure,SP_level_spellpoint_cost(op,type));
  324. #endif
  325.     return RANDOM()%(SP_level_spellpoint_cost(op,type)+ 1);
  326.     }
  327.    }
  328. #endif /*SPELL_ENCUMBRANCE*/
  329.     
  330. /*
  331.  * This is a simplification of the time it takes to cast a spell.
  332.  * In the future, the time will have to be spent before the
  333.  * spell takes effect, and the caster can possibly be disturbed.
  334.  * (maybe that should depend upon the spell cast?)
  335.  */
  336. #ifdef CASTING_TIME
  337. if (item == spellNormal && !ability ){
  338.   op->casting = -1;
  339.   op->spell_state = 1;
  340.   s = op->spell; /* set s to the cast spell */
  341.   type = op->spelltype;
  342.   stringarg = op->spellarg;
  343. }
  344. #else
  345.   /* It seems the that the patch that added spell casting times
  346.    * increased the time value of most spells by about 10.  So divide
  347.    * by 10 to get back to more normal use.
  348.    */
  349.   op->speed_left -= (s->time*PATH_TIME_MULT(op,s) / 10) * FABS(op->speed);
  350. #endif
  351.   switch((enum spellnrs) type) {
  352.   case SP_BULLET:
  353.   case SP_LARGE_BULLET:
  354.     success = fire_arch(op,dir,spellarch[type],type,1);
  355.     break;
  356.   case SP_HOLY_ORB:
  357.     success = fire_arch(op,dir,spellarch[type],type,0);
  358.     break;
  359.   case SP_S_FIREBALL:
  360.   case SP_M_FIREBALL:
  361.   case SP_L_FIREBALL:
  362.   case SP_HELLFIRE:
  363.   case SP_POISON_CLOUD:
  364.   case SP_M_MISSILE:
  365.     success = fire_arch(op,dir,spellarch[type],type, !ability);
  366.     break;
  367.   case SP_MASS_CONFUSION:
  368.   case SP_SHOCKWAVE:
  369.   case SP_COLOR_SPRAY:
  370.   case SP_FACE_OF_DEATH:
  371.   case SP_COUNTER_SPELL:
  372.   case SP_BURNING_HANDS:
  373.   case SP_PARALYZE:
  374.   case SP_SLOW:
  375.   case SP_ICESTORM:
  376.   case SP_FIREBREATH:
  377.   case SP_LARGE_ICESTORM:
  378.   case SP_BANISHMENT:    
  379.     success = cast_cone(op,dir,duration,type,spellarch[type],!ability);
  380.     break;
  381.   case SP_HOLY_WORD:
  382.   case SP_TURN_UNDEAD:
  383.     success = cast_cone(op,dir,duration+turn_bonus[op->stats.Wis],type,
  384.     spellarch[type],0);
  385.     break;
  386.   case SP_HOLY_WRATH:
  387.   case SP_INSECT_PLAGUE:
  388.   case SP_RETRIBUTION:
  389.     success = cast_smite_spell(op,dir,type);
  390.     break;
  391.   case SP_SUNSPEAR:
  392.   case SP_FIREBOLT:
  393.   case SP_FROSTBOLT:
  394.   case SP_S_LIGHTNING:
  395.   case SP_L_LIGHTNING:
  396.   case SP_STEAMBOLT:
  397.     success = fire_bolt(op,dir,type,!ability);
  398.     break;
  399.   case SP_BOMB:
  400.     success = create_bomb(op,dir,"bomb");
  401.     break;
  402.   case SP_GOLEM:
  403.   case SP_FIRE_ELEM:
  404.   case SP_WATER_ELEM:
  405.   case SP_EARTH_ELEM:
  406.   case SP_AIR_ELEM:
  407.     success = summon_monster(op,dir,spellarch[type],type);
  408.     break;
  409.   case SP_STAFF_TO_SNAKE: 
  410.     success = staff_to_snake(op,dir,spellarch[type],type);
  411.     break;
  412.   case SP_FINGER_DEATH: 
  413.     success = finger_of_death(op,dir);
  414.     break;
  415.   case SP_HOLY_SERVANT: 
  416.   case SP_SUMMON_AVATAR: 
  417.     success = summon_avatar(op,dir,spellarch[type],type);
  418.     break;
  419.   case SP_CONSECRATE: 
  420.     success = cast_consecrate(op); 
  421.     break;
  422.   case SP_SUMMON_CULT:
  423. #ifdef MULTIPLE_GODS
  424.     success = summon_cult_monsters(op,dir);
  425. #else
  426.     success = summon_pet(op,dir,item);
  427. #endif
  428.     break;
  429.   case SP_PET:
  430.     success = summon_pet(op,dir, item);
  431.     break;
  432.   case SP_D_DOOR:
  433.     /* dimension door needs the actual caster, because that is what is
  434.      * moved.
  435.      */
  436.     success = dimension_door(orig_op,dir);
  437.     break;
  438.   case SP_DARKNESS:
  439.   case SP_WALL_OF_THORNS:
  440.   case SP_CHAOS_POOL:
  441.   case SP_COUNTERWALL:
  442.   case SP_FIRE_WALL:
  443.   case SP_FROST_WALL:
  444.   case SP_EARTH_WALL:
  445.     success = magic_wall(op,dir,type);
  446.     break;
  447.   case SP_MAGIC_MAPPING:
  448.     if(op->type==PLAYER) {
  449.       spell_effect(SP_MAGIC_MAPPING, op->x, op->y, op->map);
  450.       draw_map(op);
  451.       success=1;
  452.     }
  453.     break;
  454.   case SP_FEAR:
  455.     if(op->type==PLAYER)
  456.       bonus=fear_bonus[op->stats.Cha];
  457.     else
  458.       bonus=op->head==NULL?op->level/3+1:op->head->level/3+1;
  459.     success = cast_cone(op,dir,duration+bonus,SP_FEAR,spellarch[type],!ability);
  460.     break;
  461.   case SP_WOW:
  462.     success = cast_wow(op,dir,ability, item);
  463.     break;
  464.   case SP_DESTRUCTION:
  465.     success = cast_destruction(op,5+op->stats.Int,AT_MAGIC);
  466.     break;
  467.   case SP_PERCEIVE:
  468.     success = perceive_self(op);
  469.     break;
  470.   case SP_WOR:
  471.     success = cast_wor(op);
  472.     break;
  473.   case SP_INVIS:
  474.   case SP_INVIS_UNDEAD:
  475.   case SP_IMPROVED_INVIS:
  476.     success = cast_invisible(op,type);
  477.     break;
  478.   case SP_PROBE:
  479.     success = probe(op,dir);
  480.     break;
  481.   case SP_CREATE_FOOD:
  482.     success = cast_create_food(op,dir,stringarg);
  483.     break;
  484.   case SP_EARTH_DUST:
  485.     success = cast_earth2dust(op);
  486.     break;
  487.   case SP_REGENERATION: 
  488.   case SP_BLESS:
  489.   case SP_CURSE:
  490.   case SP_HOLY_POSSESSION:
  491.   case SP_STRENGTH:
  492.   case SP_DEXTERITY:
  493.   case SP_CONSTITUTION:
  494.   case SP_CHARISMA:
  495.   case SP_ARMOUR:
  496.   case SP_PROT_COLD:
  497.   case SP_PROT_FIRE:
  498.   case SP_PROT_ELEC:
  499.   case SP_PROT_POISON:
  500.   case SP_PROT_SLOW:
  501.   case SP_PROT_DRAIN:
  502.   case SP_PROT_PARALYZE:
  503.   case SP_PROT_ATTACK:
  504.   case SP_PROT_MAGIC:
  505.   case SP_PROT_CONFUSE:
  506.   case SP_PROT_CANCEL:
  507.   case SP_PROT_DEPLETE:
  508.   case SP_LEVITATE:
  509.   case SP_HEROISM:
  510.   case SP_CONFUSION:
  511.   case SP_XRAY:
  512.   case SP_DARK_VISION:
  513.     success = cast_change_attr(op,dir,type);
  514.     break;
  515.   case SP_RESTORATION:
  516.   case SP_HEAL:
  517.   case SP_MINOR_HEAL:
  518.   case SP_MED_HEAL:
  519.   case SP_MAJOR_HEAL:
  520.   case SP_CURE_POISON:
  521.   case SP_CURE_CONFUSION:
  522.   case SP_CURE_BLINDNESS:
  523.     success = cast_heal(op,dir,type);
  524.     break;
  525.   case SP_REGENERATE_SPELLPOINTS:
  526.     success = cast_regenerate_spellpoints(op);
  527.     break;
  528.   case SP_SMALL_SPEEDBALL:
  529.   case SP_LARGE_SPEEDBALL:
  530.     success = cast_speedball(op,dir,type);
  531.     break;
  532.   case SP_POLYMORPH:
  533.     success = cast_polymorph(op,dir);
  534.     break;
  535.   case SP_CHARGING:
  536.     success = recharge(op);
  537.     break;
  538.   case SP_CANCELLATION:
  539.     success = fire_cancellation(op,dir,spellarch[type],!ability);
  540.     break;
  541.   case SP_ALCHEMY:
  542.     success = alchemy(op);
  543.     break;
  544.   case SP_REMOVE_CURSE:
  545.   case SP_REMOVE_DAMNATION:
  546.     success = remove_curse(op, type, item);
  547.     break;
  548.   case SP_IDENTIFY:
  549.     success = cast_identify(op);
  550.     break;
  551.   case SP_DETECT_MAGIC:
  552.   case SP_DETECT_MONSTER:
  553.   case SP_DETECT_EVIL:
  554.   case SP_DETECT_CURSE:
  555.   case SP_SHOW_INVIS:
  556.     success = cast_detection(op, type);
  557.     break;
  558.   case SP_AGGRAVATION:
  559.     aggravate_monsters(op);
  560.     success = 1;
  561.     break;
  562. /* peterm: following spells added */
  563.   case SP_BALL_LIGHTNING:
  564.     success = fire_arch(op,dir,find_archetype("ball_lightning"),type,!ability);
  565.     break;
  566.   case SP_METEOR_SWARM: {
  567.     int n;
  568.     n=RANDOM()%3 + RANDOM()%3 + RANDOM()%3 +3 +
  569.       SP_level_strength_adjust(op, type);
  570.     success = 1;
  571.     fire_swarm(op,dir,find_archetype("meteor"),SP_METEOR,n);
  572.     break;
  573. }
  574.  
  575.   case SP_METEOR:
  576.     success = fire_arch(op,dir,find_archetype("meteor"),type,0);
  577.     break;
  578.   case SP_MYSTIC_FIST:
  579.     success = summon_monster(op,dir,spellarch[type],type);
  580.     break;
  581.   case SP_RAISE_DEAD:
  582.   case SP_RESURRECTION:
  583.     success = cast_raise_dead_spell(op,dir,type, NULL);
  584.     break;
  585.   /* mlee */
  586.   case SP_IMMUNE_COLD:
  587.   case SP_IMMUNE_FIRE:
  588.   case SP_IMMUNE_ELEC:
  589.   case SP_IMMUNE_POISON:
  590.   case SP_IMMUNE_SLOW:
  591.   case SP_IMMUNE_DRAIN:
  592.   case SP_IMMUNE_PARALYZE:
  593.   case SP_IMMUNE_ATTACK:
  594.   case SP_IMMUNE_MAGIC:
  595.   case SP_INVULNERABILITY:
  596.   case SP_PROTECTION:
  597.   case SP_HASTE:
  598.     success=cast_change_attr(op,dir,type);
  599.     break;
  600.   /* peterm, additional spells added */
  601.   case SP_BUILD_DIRECTOR:
  602.   case SP_BUILD_BWALL:
  603.   case SP_BUILD_LWALL:
  604.   case SP_BUILD_FWALL:
  605.     success=create_the_feature(op,dir,type);
  606.     break;
  607.   case SP_RUNE_FIRE: 
  608.   case SP_RUNE_FROST:
  609.   case SP_RUNE_SHOCK: 
  610.   case SP_RUNE_BLAST: 
  611.   case SP_RUNE_DEATH: 
  612.   case SP_RUNE_ANTIMAGIC:
  613.     success = write_rune(op,dir,0,op->level,s->archname);
  614.     break;
  615.   case SP_RUNE_DRAINSP:
  616.     success = write_rune(op,dir,SP_MAGIC_DRAIN,op->level,s->archname);
  617.     break;
  618.   case SP_RUNE_TRANSFER:
  619.     success= write_rune(op,dir,SP_TRANSFER,op->level,s->archname);
  620.     break;
  621.   case SP_TRANSFER:
  622.     success = cast_transfer(op,dir);
  623.     break;
  624.   case SP_MAGIC_DRAIN:
  625.     success= drain_magic(op,dir);
  626.     break;
  627.   case SP_DISPEL_RUNE:
  628.     success = dispel_rune(op,dir,0);  /* 0 means no risk of detonating rune */
  629.     break;
  630.   case SP_SUMMON_EVIL_MONST:
  631.     if(op->type==PLAYER) return 0;
  632.     success = summon_hostile_monsters(op,op->stats.maxhp,op->race);
  633.     break;
  634.  
  635.   case SP_REINCARNATION:
  636.     {
  637.       object * dummy;
  638.       if(stringarg==NULL) {
  639.     new_draw_info(NDI_UNIQUE, 0,op,"Reincarnate WHO?");
  640.     success=0;
  641.     break;
  642.       }
  643.       dummy = get_object();
  644.       dummy->name = add_string(stringarg);
  645.       success = cast_raise_dead_spell(op,dir,type, dummy);
  646.       free_object(dummy);
  647.     }
  648.     break;
  649.   case SP_RUNE_MAGIC:
  650.     { int total_sp_cost, spellinrune;
  651.       spellinrune=look_up_spell_by_name(op,stringarg);
  652.       if(spellinrune!=-1) {
  653.       total_sp_cost=SP_level_spellpoint_cost(op,spellinrune)
  654.             +spells[spellinrune].sp;
  655.     if(op->stats.sp<total_sp_cost) {
  656.       new_draw_info(NDI_UNIQUE, 0,op,"Not enough spellpoints.");
  657. #ifdef CASTING_TIME
  658.       /* free the spell arg */
  659.       if(stringarg) {free(stringarg);stringarg=NULL; };
  660. #endif
  661.       return 0;
  662.     }
  663.     success=write_rune(op,dir,spellinrune,op->level,stringarg);
  664.     return (success ? total_sp_cost : 0);
  665.       }
  666. #ifdef CASTING_TIME
  667.       /* free the spell arg */
  668.       if(stringarg) {free(stringarg);stringarg=NULL; };
  669. #endif
  670.       return 0;
  671.     }
  672.     break;
  673.   case SP_RUNE_MARK:
  674.     success=write_rune(op,dir,0,-2,stringarg);
  675. #ifdef CASTING_TIME
  676.       /* free the spell arg */
  677.       if(stringarg) {free(stringarg);stringarg=NULL; };
  678. #endif
  679.  
  680.  
  681.     break;
  682.   case SP_LIGHT:
  683.     success = cast_light(op,dir);
  684.     break;
  685.   case SP_DAYLIGHT:
  686.     success = cast_daylight(op); 
  687.     break; 
  688.   case SP_NIGHTFALL:
  689.     success = cast_nightfall(op);
  690.     break;
  691.   case SP_FAERY_FIRE:
  692.     success = cast_faery_fire(op);
  693.     break;
  694.   case SP_CAUSE_LIGHT:
  695.   case SP_CAUSE_HEAVY:
  696.   case SP_CAUSE_MEDIUM:
  697.   case SP_CAUSE_CRITICAL:
  698.     success = fire_arch(op,dir,spellarch[type],type,1); /* don't want to OR magic */
  699.   break;
  700.   case SP_SUMMON_FOG:
  701.     success = summon_fog(op,dir,type);
  702.     break;
  703.   case SP_PACIFY:
  704.     cast_pacify(op,caster,spellarch[type],type);
  705.     success = 1;
  706.       break;
  707.   case SP_COMMAND_UNDEAD:
  708.     cast_charm_undead(op,spellarch[type],type);
  709.     success = 1;
  710.       break;
  711.   case SP_CHARM:
  712.     cast_charm(op,spellarch[type],type);
  713.     success = 1;
  714.     break;
  715.   /* huma */
  716.   case SP_CREATE_MISSILE:
  717.     success = cast_create_missile(op,dir,stringarg);
  718.     break;
  719.  
  720.   }
  721. #ifdef SOUND_EFFECTS
  722.   play_sound_map(op->map, op->x, op->y, SOUND_CAST_SPELL_0 + type);
  723. #endif
  724. #ifdef CASTING_TIME
  725.       /* free the spell arg */
  726.       if(stringarg) {free(stringarg);stringarg=NULL; };
  727. #endif
  728.  
  729. #ifdef SPELLPOINT_LEVEL_DEPEND
  730.   return success?SP_level_spellpoint_cost(op,type):0;
  731. #else
  732.   return success?(s->sp*PATH_SP_MULT(op,s)):0;
  733. #endif
  734. }
  735.  
  736.  
  737. int cast_create_obj(object *op,object *new_op, int dir)
  738. {
  739.   if(dir && blocked(op->map,op->x+freearr_x[dir],op->y+freearr_y[dir])) {
  740.     new_draw_info(NDI_UNIQUE, 0,op,"Something is in the way.");
  741.     new_draw_info(NDI_UNIQUE, 0,op,"You cast it at your feet.");
  742.     dir = 0;
  743.   }
  744.   new_op->x=op->x+freearr_x[dir];
  745.   new_op->y=op->y+freearr_y[dir];
  746.   insert_ob_in_map(new_op,op->map);
  747.   return dir;
  748. }
  749.  
  750. int summon_monster(object *op,int dir,archetype *at,int spellnum) {
  751.   object *tmp;
  752.   if(op->type==PLAYER)
  753.     if(op->contr->golem!=NULL&&!QUERY_FLAG(op->contr->golem,FLAG_FREED)) {
  754.       control_golem(op->contr->golem,dir);
  755.       return 0;
  756.     }
  757.   if(!dir)
  758.     dir=find_free_spot(NULL,op->map,op->x,op->y,1,9);
  759.   if(blocked(op->map,op->x+freearr_x[dir],op->y+freearr_y[dir])) {
  760.     new_draw_info(NDI_UNIQUE, 0,op,"There is something in the way.");
  761.     if(op->type==PLAYER)
  762.       op->contr->count_left=0;
  763.     return 0;
  764.   }
  765.   tmp=arch_to_object(at);
  766.   if(op->type==PLAYER) {
  767.     CLEAR_FLAG(tmp, FLAG_MONSTER);
  768.     tmp->stats.exp=0;
  769.     add_friendly_object(tmp);
  770.     tmp->type=GOLEM;
  771. /* Don't see any point in setting this when monsters summon monsters: */
  772.     set_owner(tmp,op);
  773.     op->contr->golem=tmp;
  774.     /* give the player control of the golem */
  775.     op->contr->shoottype=range_scroll;
  776.   } else {
  777.     if(QUERY_FLAG(op, FLAG_FRIENDLY)) {
  778.       object *owner = get_owner(op);
  779.       if(owner != NULL) /* For now, we transfer ownership */
  780.         set_owner(tmp,owner);
  781.       tmp->move_type = PETMOVE;
  782.       add_friendly_object(tmp);
  783.       SET_FLAG(tmp, FLAG_FRIENDLY);
  784.     }
  785.     SET_FLAG(tmp, FLAG_MONSTER);
  786.   }
  787.   /*  This sets the level dependencies on dam and hp for monsters */
  788.   tmp->stats.hp = SP_PARAMETERS[spellnum].bdur +
  789.              10 * SP_level_strength_adjust(op,spellnum);
  790.   tmp->stats.dam= SP_PARAMETERS[spellnum].bdam +
  791.              2* SP_level_dam_adjust(op,spellnum);
  792.   if(tmp->stats.dam<0) tmp->stats.dam=127;  /*seen this go negative!*/
  793.  /*  make experience increase in proportion to the strength of the summoned creature. */
  794.   tmp->stats.exp *= SP_level_spellpoint_cost(op,spellnum)/spells[spellnum].sp;
  795.   tmp->speed_left= -1;
  796.   tmp->x=op->x+freearr_x[dir],tmp->y=op->y+freearr_y[dir];
  797.   tmp->direction=dir;
  798.   insert_ob_in_map(tmp,op->map);
  799.   return 1;
  800. }
  801.  
  802.  
  803. int ok_to_put_more(mapstruct *m,int x,int y,object *op,int immune_stop) {
  804.   object *tmp,*head;
  805.   for(tmp=get_map_ob(m,x,y);tmp!=NULL;tmp=tmp->above) {
  806.     head=tmp->head==NULL?tmp:tmp->head;
  807.     if((QUERY_FLAG(op, FLAG_ALIVE) && head->immune & immune_stop) ||
  808.        (head->stats.maxhp == op->stats.maxhp && head->type == op->type))
  809.       return 0;
  810.   }
  811.   return 1;
  812. }
  813.  
  814.  
  815.  
  816.  
  817.  
  818.  
  819. int fire_bolt(object *op,int dir,int type,int magic) {
  820.   object *tmp=NULL;
  821.   if (!spellarch[type])
  822.     return 0;
  823.   tmp=arch_to_object(spellarch[type]);
  824.   if(tmp==NULL)
  825.     return 0;
  826.   /*  peterm:  level dependency for bolts  */
  827.   tmp->stats.dam = SP_PARAMETERS[type].bdam + SP_level_dam_adjust(op,type);
  828.   tmp->stats.hp = SP_PARAMETERS[type].bdur + SP_level_strength_adjust(op,type);
  829.   if(magic)
  830.     tmp->attacktype|=AT_MAGIC;
  831.   tmp->x=op->x,tmp->y=op->y;
  832.   tmp->direction=dir;
  833.   if(QUERY_FLAG(tmp, FLAG_IS_TURNABLE))
  834.     tmp->face=&new_faces[tmp->arch->faces[dir]];
  835.   set_owner(tmp,op);
  836. #if 0
  837.   if(op->type==PLAYER)
  838.     tmp->stats.wc=5+(op->contr->shootstrength-5)/5,
  839.     tmp->stats.exp=(op->contr->shootstrength-5)/3+12,
  840.     tmp->stats.hp=8+(op->contr->shootstrength-5)/8;
  841. #endif
  842.   tmp->x+=DIRX(tmp),tmp->y+=DIRY(tmp);
  843.   if(wall(op->map,tmp->x,tmp->y)) {
  844.     if(!QUERY_FLAG(tmp, FLAG_REFLECTING)) {
  845.       free_object(tmp);
  846.       return 0;
  847.     }
  848.     tmp->x=op->x,tmp->y=op->y;
  849.     tmp->direction=absdir(tmp->direction+4);
  850.   }
  851.   insert_ob_in_map(tmp,op->map);
  852.   move_bolt(tmp);
  853.   return 1;
  854. }
  855.  
  856. /*  peterm  added a type field to fire_arch.  Needed it for making
  857.     fireball etall level dependent.
  858.     Later added a ball-lightning firing routine.
  859.  */
  860.  
  861. int fire_arch(object *op,int dir,archetype *at, int type, int magic) {
  862.   object *tmp, *env;
  863.  
  864.   if(at==NULL)
  865.     return 0;
  866.   for(env=op;env->env!=NULL;env=env->env);
  867.   if (env->map == NULL)
  868.     return 0;
  869.   tmp=arch_to_object(at);
  870.   if(tmp==NULL)
  871.     return 0;
  872.   tmp->stats.sp=type;
  873.   tmp->stats.dam=SP_PARAMETERS[type].bdam+SP_level_dam_adjust(op,type);
  874.   tmp->stats.hp=SP_PARAMETERS[type].bdur+SP_level_strength_adjust(op,type);
  875.   tmp->x=op->x,tmp->y=op->y;
  876.   tmp->direction=dir;
  877. #ifdef MULTIPLE_GODS /* needed for AT_HOLYWORD,AT_GODPOWER stuff */
  878.   if(tmp->attacktype&AT_HOLYWORD||tmp->attacktype&AT_GODPOWER)
  879.           if(!tailor_god_spell(tmp,op,get_god(op))) return 0; 
  880. #endif 
  881.   if(magic)
  882.     tmp->attacktype|=AT_MAGIC;
  883.   if(QUERY_FLAG(tmp, FLAG_IS_TURNABLE))
  884.     tmp->face=&new_faces[tmp->arch->faces[dir]];
  885. #if 0
  886.   if(op->type==PLAYER)
  887.     tmp->stats.hp=(op->contr->shootstrength-10)/10+10;
  888. #endif
  889.   set_owner(tmp,op);
  890.   if(op->type==PLAYER)
  891.     D_LOCK(op);
  892.   insert_ob_in_map(tmp,op->map);
  893.   /* object was used when it was inserted into the map - don't do anything
  894.    * more
  895.    */
  896.   if (QUERY_FLAG(tmp, FLAG_FREED)) return 1;
  897.   switch(type) {
  898.     case SP_M_MISSILE:
  899.     move_missile(tmp);
  900.     break;
  901.     case SP_BALL_LIGHTNING:
  902.     tmp->stats.food=SP_PARAMETERS[type].bdur +
  903.                       SP_level_strength_adjust(op,type);
  904.     move_ball_lightning(tmp);
  905.     break;
  906.     default:
  907.     move_fired_arch(tmp);
  908.   }
  909.   if(op->type==PLAYER)
  910.     D_UNLOCK(op);
  911.   return 1;
  912. }
  913.  
  914. int
  915. cast_cone(object *op, int dir, int strength, int spell_type,archetype *spell_arch, int magic)
  916. {
  917.   object *tmp;
  918.   int i,success=0,range_min= -1,range_max=1;
  919.  
  920.   if(!dir)
  921.     range_min= -3,range_max=4,strength/=2;
  922.  
  923.   for(i=range_min;i<=range_max;i++) {
  924.     int x=op->x+freearr_x[absdir(dir+i)],
  925.         y=op->y+freearr_y[absdir(dir+i)];
  926.     if(wall(op->map,x,y))
  927.       continue;
  928.     success=1;
  929.     tmp=arch_to_object(spell_arch);
  930.     set_owner(tmp,op);
  931. /*  Make face of death work? */
  932.     /* tmp->level=op->level;  */
  933.     tmp->level=SK_level(op); /* need to use the cleric level, not overall value -b.t. */ 
  934.     tmp->x=x,tmp->y=y;
  935. #ifdef MULTIPLE_GODS /* holy word stuff */                
  936.     if((tmp->attacktype&AT_HOLYWORD)||(tmp->attacktype&AT_GODPOWER))
  937.             if(!tailor_god_spell(tmp,op,get_god(op))) return 0;  
  938. #endif
  939.     /*if (tmp->type != CONE)
  940.       tmp->type = CONE; */
  941.  
  942.     if(magic)
  943.       tmp->attacktype|=AT_MAGIC;  /* JWI cone attacks should be considered
  944.                                      magical in nature ;) */
  945.     if(dir)
  946.       tmp->stats.sp=dir;
  947.     else
  948.       tmp->stats.sp=i;
  949.     tmp->stats.hp=strength+SP_level_strength_adjust(op,spell_type);
  950.     tmp->stats.dam=SP_PARAMETERS[spell_type].bdam +
  951.                   SP_level_dam_adjust(op,spell_type); 
  952.     tmp->stats.maxhp=tmp->count;
  953.     SET_FLAG(tmp, FLAG_FLYING);
  954.     insert_ob_in_map(tmp,op->map);
  955.   }
  956.   return success;
  957. }
  958.  
  959. void move_cone(object *op) {
  960.   int i;
  961.  
  962.   if (QUERY_FLAG(op, FLAG_LIFESAVE)) {/* lava saves it's life, but not yours  :) */
  963.       hit_map(op,0,op->attacktype);
  964.       return;
  965.   }
  966.   if(get_owner(op)==NULL) {
  967.     remove_ob(op);
  968.     free_object(op);
  969.     return;
  970.   }
  971.   /* Hit map returns 1 if it hits a monster.  If it does, set
  972.    * food to 1, which will stop the cone from progressing.
  973.    */
  974.   op->stats.food |= hit_map(op,0,op->attacktype);
  975.   if((op->stats.hp-=2)<0) {
  976.     if(op->stats.exp) {
  977.       op->speed = 0;
  978.       update_ob_speed(op);
  979.       op->stats.exp=0;
  980.       op->stats.sp=0; /* so they will join */
  981.     } else {
  982.       remove_ob(op);
  983.       free_object(op);
  984.     }
  985.     return;
  986.   }
  987.   if(op->stats.food)   return;
  988.   op->stats.food=1;
  989.   for(i= -1;i<2;i++) {
  990.     int x=op->x+freearr_x[absdir(op->stats.sp+i)],
  991.         y=op->y+freearr_y[absdir(op->stats.sp+i)];
  992.     if(!wall(op->map,x,y)&&ok_to_put_more(op->map,x,y,op,op->attacktype) &&
  993.        !blocks_view(op->map,x,y)) {
  994.       object *tmp=arch_to_object(op->arch);
  995.       set_owner(tmp,op->owner);
  996.       tmp->x=x, tmp->y=y;
  997. /* added to make face of death work,and counterspell */
  998.       /* tmp->level=op->level;*/  
  999.       tmp->level=SK_level(op);  
  1000. #ifdef MULTIPLE_GODS /* holy word stuff */
  1001.       if(tmp->attacktype&AT_HOLYWORD||tmp->attacktype&AT_GODPOWER) 
  1002.             if(!tailor_god_spell(tmp,op,-1)) return;
  1003. #endif
  1004.       tmp->stats.sp=op->stats.sp,tmp->stats.hp=op->stats.hp+1;
  1005.       tmp->stats.maxhp=op->stats.maxhp;
  1006.       tmp->attacktype=op->attacktype;
  1007.       insert_ob_in_map(tmp,op->map);
  1008.     }
  1009.   }
  1010. }
  1011.  
  1012. void fire_a_ball(object *op,int dir,int strength) {
  1013.   object *tmp=clone_arch(FBULLET);
  1014.  
  1015.   if(!dir)
  1016.     LOG(llevError,"Tried to fire a ball without direction.\n");
  1017.   set_owner(tmp,op);
  1018.   tmp->direction=dir;
  1019.   tmp->x=op->x,tmp->y=op->y;
  1020.   tmp->speed = 1;
  1021.   update_ob_speed(tmp);
  1022.   tmp->stats.hp=strength;
  1023.   tmp->face=&new_faces[tmp->arch->faces[dir]];
  1024.   SET_FLAG(tmp, FLAG_FLYING);
  1025.   insert_ob_in_map(tmp,op->map);
  1026.   move_fired_arch(tmp);
  1027. }
  1028.  
  1029. void explosion(object *op) {
  1030.   object *tmp;
  1031.   mapstruct *m=op->map; /* In case we free b */
  1032.   int i;
  1033.  
  1034.   if(--(op->stats.hp)<0) {
  1035.     remove_ob(op);
  1036.     free_object(op);
  1037.     return;
  1038.   }
  1039.   if(op->above!=NULL&&op->above->type!=PLAYER) {
  1040.     remove_ob(op);
  1041.     insert_ob_in_map(op,op->map);
  1042.   }
  1043.   hit_map(op,0,op->attacktype);
  1044.   if(op->stats.hp>2&&!op->value) {
  1045.     op->value=1;
  1046.     for(i=1;i<9;i++) {
  1047.       int dx,dy;
  1048.       if(wall(op->map,dx=op->x+freearr_x[i],dy=op->y+freearr_y[i]))
  1049.         continue;
  1050.       if(blocks_view(op->map, dx, dy))
  1051.         continue;
  1052.       if(ok_to_put_more(op->map,dx,dy,op,op->attacktype)) {
  1053.         tmp=get_object();
  1054.         copy_object(op,tmp); /* This is probably overkill on slow computers.. */
  1055.         tmp->state=0;
  1056.         tmp->speed_left= -0.21;
  1057.         tmp->stats.hp--;
  1058.         tmp->value=0;
  1059.         tmp->x=dx,tmp->y=dy;
  1060.         insert_ob_in_map(tmp,m);
  1061.       }
  1062.     }
  1063.   }
  1064. }
  1065.  
  1066. int reflwall(mapstruct *m,int x,int y) {
  1067.   object *op;
  1068.   if(out_of_map(m,x,y)) return 0;
  1069.   for(op=get_map_ob(m,x,y);op!=NULL;op=op->above)
  1070.     if(QUERY_FLAG(op, FLAG_REFL_SPELL))
  1071.       return 1;
  1072.   return 0;
  1073. }
  1074.  
  1075. void move_bolt(object *op) {
  1076.   object *tmp;
  1077.   int w,r;
  1078.   if(--(op->stats.hp)<0) {
  1079.     remove_ob(op);
  1080.     free_object(op);
  1081.     return;
  1082.   }
  1083.   hit_map(op,0,op->attacktype);
  1084.   if(!op->value&&--(op->stats.exp)>0) {
  1085.     op->value=1;
  1086.     if(!op->direction)
  1087.       return;
  1088.     /*
  1089.      * The bolt stops if it hits someone who is immune to it.
  1090.      */
  1091.     tmp=get_map_ob(op->map,op->x,op->y);
  1092.     while(tmp!=NULL&&(!QUERY_FLAG(tmp, FLAG_ALIVE)||!(tmp->immune&op->attacktype)))
  1093.       tmp=tmp->above;
  1094.     if(tmp!=NULL) {
  1095.       remove_ob(op);
  1096.       free_object(op);
  1097.       return;
  1098.     }
  1099.     if(blocks_view(op->map,op->x+DIRX(op),op->y+DIRY(op)))
  1100.       return;
  1101.     w=wall(op->map,op->x+DIRX(op),op->y+DIRY(op));
  1102.     r=reflwall(op->map,op->x+DIRX(op),op->y+DIRY(op));
  1103.     if(w&&!QUERY_FLAG(op, FLAG_REFLECTING))
  1104.       return;
  1105.     if(w||r) { /* We're about to bounce */
  1106.       if(!QUERY_FLAG(op, FLAG_REFLECTING))
  1107.         return;
  1108.       op->value=0;
  1109.       if(op->direction&1)
  1110.         op->direction=absdir(op->direction+4);
  1111.       else {
  1112.         int left= wall(op->map,op->x+freearr_x[absdir(op->direction-1)],
  1113.                               op->y+freearr_y[absdir(op->direction-1)]),
  1114.             right=wall(op->map,op->x+freearr_x[absdir(op->direction+1)],
  1115.                               op->y+freearr_y[absdir(op->direction+1)]);
  1116.         if(left==right)
  1117.           op->direction=absdir(op->direction+4);
  1118.         else if(left)
  1119.           op->direction=absdir(op->direction+2);
  1120.         else if(right)
  1121.           op->direction=absdir(op->direction-2);
  1122.       }
  1123.       update_turn_face(op); /* A bolt *must* be IS_TURNABLE */
  1124.       return;
  1125.     }
  1126.     else { /* Create a copy of this object and put it ahead */
  1127.       tmp=get_object();
  1128.       copy_object(op,tmp);
  1129.       tmp->speed_left= -0.1;
  1130.       tmp->value=0;
  1131.       tmp->stats.hp++;
  1132.       tmp->x+=DIRX(tmp),tmp->y+=DIRY(tmp);
  1133.       insert_ob_in_map(tmp,op->map);
  1134.       if (!tmp->stats.food) {
  1135.         tmp->stats.food = 1;
  1136.         move_bolt(tmp);
  1137.       } else
  1138.         tmp->stats.food = 0;
  1139.     }
  1140.   }
  1141. }
  1142.  
  1143. void move_golem(object *op) {
  1144.   if(QUERY_FLAG(op, FLAG_MONSTER))
  1145.     return; /* Has already been moved */
  1146.   if(get_owner(op)==NULL) {
  1147.     LOG(llevDebug,"Golem without owner destructed.\n");
  1148.     remove_ob(op);
  1149.     free_object(op);
  1150.     return;
  1151.   }
  1152.   if(--op->stats.hp<0) {
  1153.     new_draw_info(NDI_UNIQUE, 0,op->owner,"Your golem dissolved.");
  1154.     remove_friendly_object(op);
  1155.     op->owner->contr->golem=NULL;
  1156.     remove_ob(op);
  1157.     free_object(op);
  1158.     return;
  1159.   }
  1160.   if(!move_ob(op,op->direction)&&
  1161.      !out_of_map(op->map,op->x+freearr_x[op->direction],
  1162.                  op->y+freearr_y[op->direction])) {
  1163.     update_object(op);
  1164.     hit_map(op,op->direction,AT_PHYSICAL);
  1165.   }
  1166. }
  1167.  
  1168. void control_golem(object *op,int dir) {
  1169.   op->direction=dir;
  1170. }
  1171.  
  1172.  
  1173. void move_missile(object *op) {
  1174.   int i;
  1175.   object *owner;
  1176.  
  1177.   remove_ob(op);
  1178.   owner = get_owner(op);
  1179.   if (owner == (object *) NULL) {
  1180.     free_object(op);
  1181.     return;
  1182.   }
  1183.  
  1184.   op->x+=DIRX(op),op->y+=DIRY(op);
  1185.   if(!op->direction||wall(op->map,op->x,op->y)||
  1186.      blocks_view(op->map,op->x,op->y)) {
  1187.     free_object(op);
  1188.     return;
  1189.   }
  1190.   if(blocked(op->map,op->x,op->y)) {
  1191.     hit_map(op,0,AT_MAGIC);
  1192.     free_object(op);
  1193.     return;
  1194.   }
  1195.   i=find_dir(op->map,op->x,op->y,get_owner(op));
  1196.   if(i&&i!=op->direction){
  1197.     op->direction=absdir(op->direction+((op->direction-i+8)%8<4?-1:1));
  1198.     op->face=&new_faces[op->arch->faces[op->direction]];
  1199.   }
  1200.   insert_ob_in_map(op,op->map);
  1201. }
  1202.  
  1203. int explode_object(object *op) {
  1204.   object *tmp, *victim, *owner, *env;
  1205.  
  1206.   if(out_of_map(op->map,op->x,op->y))  /*  peterm:  check for out of map obj's.*/
  1207.     {
  1208.       return 0;
  1209.     }
  1210.   for(env=op;env->env!=NULL;env=env->env);
  1211.   if (env->map == NULL)
  1212.     return 0;
  1213.   if(op->other_arch==NULL)
  1214.     return 0;
  1215.   tmp=arch_to_object(op->other_arch);
  1216.  
  1217.   /* peterm: Hack added to make objects be able to both hit for damage and
  1218.     then explode.  */
  1219.   if(op->attacktype){
  1220.       for(victim=get_map_ob(op->map,op->x,op->y);victim!=NULL;victim=victim->above)
  1221.         if(QUERY_FLAG(victim,FLAG_ALIVE))
  1222.           break;
  1223.       hit_map(op,0,op->attacktype);
  1224.       /* Should hit_map also be doing this?  Why call hit_player
  1225.        * again?  Also, make sure victim has not been killed - it
  1226.        * is possible that hit_map killed the object.
  1227.        */
  1228.       if(victim!=NULL && !QUERY_FLAG(victim,FLAG_FREED))
  1229.      hit_player(victim,op->stats.dam,op,op->attacktype);
  1230.     }
  1231.  
  1232.   /*  peterm:  hack added to make fireballs and other explosions level
  1233.   **  dependent:  mark*/
  1234.  
  1235.   /*  op->stats.sp stores the spell which made this object here. */
  1236.   if(op->owner)
  1237.       tmp->stats.dam += SP_level_dam_adjust(op->owner,op->stats.sp);
  1238.   if(op->attacktype&AT_MAGIC)
  1239.     tmp->attacktype|=AT_MAGIC;
  1240.   if((owner = get_owner(op)) != (object *) NULL) {
  1241.     set_owner(tmp,owner);
  1242.     if(op->chosen_skill && (op->chosen_skill != tmp->chosen_skill)){
  1243.           tmp->exp_obj = op->exp_obj;
  1244.           tmp->chosen_skill = op->chosen_skill;
  1245.     }
  1246.   }
  1247.   if(op->stats.hp)
  1248.     tmp->stats.hp=op->stats.hp;
  1249.   tmp->stats.maxhp=op->count; /* Unique ID */
  1250.   tmp->x=env->x,tmp->y=env->y;
  1251.  
  1252. #ifdef MULTIPLE_GODS /* needed for AT_HOLYWORD stuff -b.t. */
  1253.   if(tmp->attacktype&AT_HOLYWORD||tmp->attacktype&AT_GODPOWER) 
  1254.           if(!tailor_god_spell(tmp,op,-1)) return 0;   
  1255. #endif
  1256.  
  1257.   if (wall(env->map,env->x,env->y))
  1258.     tmp->x-=DIRX(env),tmp->y-=DIRY(env);
  1259.   if (out_of_map(env->map, env->x, env->y))
  1260.     free_object(tmp);
  1261.   else
  1262.     insert_ob_in_map(tmp,env->map);
  1263.   free_object(op);
  1264.   return 1;
  1265. }
  1266.  
  1267. void check_fired_arch(object *op) {
  1268.   if(blocked(op->map,op->x,op->y)) {
  1269.     object *tmp;
  1270.     remove_ob(op);
  1271.     if(explode_object(op))
  1272.       return;
  1273.     for(tmp=get_map_ob(op->map,op->x,op->y);tmp!=NULL;tmp=tmp->above)
  1274.       if(QUERY_FLAG(tmp, FLAG_ALIVE))
  1275.         break;
  1276.     if(tmp!=NULL)
  1277.       op->stats.dam-=hit_player(tmp,op->stats.dam,op,op->attacktype);
  1278.     if(blocked(op->map,op->x,op->y)) {
  1279.       free_object(op);
  1280.       return;
  1281.     }
  1282.     insert_ob_in_map(op,op->map);
  1283.   }
  1284. }
  1285.  
  1286. void move_fired_arch(object *op) {
  1287.   remove_ob(op);
  1288.  
  1289.   /* peterm:  added to make comet leave a trail of burnouts 
  1290.     it's an unadulterated hack, but the effect is cool.    */
  1291.   if(op->stats.sp == SP_METEOR)
  1292.   {  
  1293.       object * tmp1=arch_to_object(find_archetype("fire_trail"));
  1294.         tmp1->x = op->x; tmp1->y = op->y;
  1295.         insert_ob_in_map(tmp1,op->map);
  1296.   }  /* end addition.  */
  1297.  
  1298.   op->x+=DIRX(op),op->y+=DIRY(op);
  1299.   if(!op->direction||wall(op->map,op->x,op->y)) {
  1300.     if(explode_object(op))
  1301.       return;
  1302.     free_object(op);
  1303.     return;
  1304.   }
  1305.   if(reflwall(op->map,op->x,op->y)) {
  1306.     op->direction=absdir(op->direction+4);
  1307.     insert_ob_in_map(op,op->map);
  1308.     update_turn_face(op);
  1309.     return;
  1310.   }
  1311.   if(blocked(op->map,op->x,op->y)) {
  1312.     object *tmp;
  1313.     if(explode_object(op))
  1314.       return;
  1315.     for(tmp=get_map_ob(op->map,op->x,op->y);tmp!=NULL;tmp=tmp->above)
  1316.       if(QUERY_FLAG(tmp, FLAG_ALIVE))
  1317.         break;
  1318.     if(tmp!=NULL) {
  1319.       /* Certain items, like speedballs, have attacktype ghosthit.
  1320.        * hit_player wants to remove the object after it hits the player.
  1321.        * Since it is already removed, just don't make it ghosthit, and
  1322.        * remove it here
  1323.        */
  1324.       if (op->attacktype & AT_GHOSTHIT) {
  1325.     hit_player(tmp,op->stats.dam,op,(op->attacktype & ~AT_GHOSTHIT));
  1326.     free_object(op);
  1327.     return;
  1328.       }
  1329.       else
  1330.         op->stats.dam-=hit_player(tmp,op->stats.dam,op,op->attacktype);
  1331.     }
  1332.     if(blocked(op->map,op->x,op->y)) {
  1333.       free_object(op);
  1334.       return;
  1335.     }
  1336.   }
  1337.   insert_ob_in_map(op,op->map);
  1338. }
  1339.  
  1340.  
  1341. void drain_rod_charge(object *rod) {
  1342.   rod->stats.hp -= spells[rod->stats.sp].sp;
  1343.   if (QUERY_FLAG(rod, FLAG_ANIMATE))
  1344.     fix_rod_speed(rod);
  1345. }
  1346.  
  1347. void fix_rod_speed(object *rod) {
  1348.   rod->speed = (FABS(rod->arch->clone.speed)*rod->stats.hp) /
  1349.                (float)rod->stats.maxhp;
  1350.   if (rod->speed < 0.02)
  1351.     rod->speed = 0.02;
  1352.   update_ob_speed(rod);
  1353. }
  1354.  
  1355.  
  1356. /*  this function is commonly used to find a friendly target for
  1357. spells such as heal or protection or armour  */
  1358.  
  1359. object *find_target_for_friendly_spell(object *op,int dir) 
  1360. { object *tmp;
  1361.   if(op->type!=PLAYER&&op->type!=RUNE) {
  1362.     tmp=get_owner(op);
  1363.     /* If the owner does not exist, or is not a monster, than apply the spell
  1364.      * to the caster.
  1365.      */
  1366.     if(!tmp || !QUERY_FLAG(tmp,FLAG_MONSTER)) tmp=op;
  1367.   }
  1368.   else
  1369.     for(tmp=get_map_ob(op->map,op->x+freearr_x[dir],op->y+freearr_y[dir]);
  1370.         tmp!=NULL;
  1371.         tmp=tmp->above)
  1372.       if(tmp->type==PLAYER)
  1373.         break;
  1374.   if(tmp==NULL)               /* didn't find a player there, look in current square for a player */
  1375.     for(tmp=get_map_ob(op->map,op->x,op->y);tmp!=NULL;tmp=tmp->above)
  1376.       if(tmp->type==PLAYER)
  1377.         break;
  1378.   return tmp;
  1379. }
  1380.  
  1381.  
  1382. /*  peterm: ball lightning mover.  */
  1383. /*  ball lightning automatically seeks out a victim, if
  1384.     it sees any monsters close enough.  */
  1385.  
  1386. void move_ball_lightning(object *op) {
  1387.     int i,nx,ny,tx,ty;
  1388.     remove_ob(op);
  1389.     nx=op->x+DIRX(op);
  1390.     ny=op->y+DIRY(op);
  1391.     ty=op->y;
  1392.     tx=op->x;  /*  the following logic makes sure that the ball
  1393.             doesn't move into a wall, and makes
  1394.             sure that it will move along a wall to try and
  1395.             get at it's victim.  */
  1396.     if(!wall(op->map, nx, ny)&&!blocks_view(op->map,nx,ny)) {
  1397.     tx=nx;
  1398.     ty=ny;
  1399.     }
  1400.     else
  1401.     {  i=RANDOM()%2;
  1402.     if(i) {
  1403.     if(!wall(op->map,op->x,ny)&&!blocks_view(op->map,op->x,ny)) ty=ny;
  1404.     else if(!wall(op->map,nx,op->y)&&!blocks_view(op->map,nx,op->y)) tx=nx;
  1405.     }
  1406.     else {
  1407.     if(!wall(op->map,nx,op->y)&&!blocks_view(op->map,nx,op->y)) tx=nx;
  1408.     else if(!wall(op->map,op->x,ny)&&!blocks_view(op->map,op->x,ny)) ty=ny;
  1409.     }
  1410.     }
  1411.     op->y=ty;
  1412.     op->x=tx;
  1413.  
  1414.     if(blocked(op->map,op->x,op->y)) hit_map(op,0,op->attacktype);
  1415.  
  1416.     i=spell_find_dir(op->map,op->x,op->y,get_owner(op));
  1417.  
  1418.     if(i) op->direction=i;
  1419.     insert_ob_in_map(op,op->map);
  1420. }
  1421.     
  1422. /* raytrace:
  1423.  * spell_find_dir(map, x, y, exclude) will search first the center square
  1424.  * then some close squares in the given map at the given coordinates for
  1425.  * live objects.
  1426.  * It will not considered the object given as exlude among possible
  1427.  * live objects.
  1428.  * It returns the direction toward the first/closest live object if finds
  1429.  * any, otherwise 0.
  1430.  */
  1431.  
  1432. int spell_find_dir(mapstruct *m, int x, int y, object *exclude) {
  1433.   int i,max=SIZEOFFREE;
  1434.   object *tmp;
  1435.   if (exclude && exclude->head)
  1436.     exclude = exclude->head;
  1437.  
  1438.   for(i=(RANDOM()%8)+1;i<max;i++) {
  1439.     if(wall(m, x+freearr_x[i],y+freearr_y[i]))
  1440.       max=maxfree[i];
  1441.     else {
  1442.       tmp=get_map_ob(m,x+freearr_x[i],y+freearr_y[i]);
  1443.       while(tmp!=NULL && ((tmp!=NULL&&!QUERY_FLAG(tmp,FLAG_MONSTER)&&
  1444.         tmp->type!=PLAYER&&!QUERY_FLAG(tmp,FLAG_GENERATOR)) ||
  1445.     (tmp == exclude || (tmp->head && tmp->head == exclude))))
  1446.                 tmp=tmp->above;
  1447.       if(tmp!=NULL)
  1448.         return freedir[i];
  1449.     }
  1450.   }
  1451.   return 0;
  1452. }
  1453.  
  1454.  
  1455. /* peterm:  */
  1456.  
  1457. /*  peterm:  the following defines the parameters for all the 
  1458. spells.  
  1459.     bdam:  base damage or hp of spell or summoned monster
  1460.   bdur:  base duration of spell or base range
  1461.   ldam:  levels you need over the min for the spell to gain one dam
  1462.   ldur:  levels you need over the min for the spell to gain one dur
  1463. */
  1464.  
  1465.  
  1466. /*  The following adjustments to spell strength are done in the
  1467. philosophy that the longer one knows a spell, the better one
  1468. should get at it.  So the more experience levels you are above
  1469. the minimum for knowing a spell, the more effective it becomes. 
  1470. most of the following adjustments are for damage only, some are
  1471. for turning undead and whatnot.  
  1472.  
  1473.   The arrays are defined in spells.h*/
  1474.  
  1475. /* July 1995 - I changed the next 3 functions slightly by replacing
  1476.  * the casters level (op->level) with the skill level (SK_level(op)) 
  1477.  * instead for when we have compiled with ALLOW_SKILLS - b.t. 
  1478.  */
  1479.  
  1480. int SP_level_dam_adjust(object *op, int spell_type)
  1481. {  int adj;
  1482. #ifdef ALLOW_SKILLS
  1483.    int level=SK_level(op)+path_level_mod(op, spell_type);
  1484. #else
  1485.    int level=op->level+path_level_mod(op, spell_type);
  1486. #endif
  1487.  
  1488.     adj=(level-spells[spell_type].level);
  1489.     if(adj < 0) adj=0;
  1490.     if(SP_PARAMETERS[spell_type].ldam)
  1491.     adj/=SP_PARAMETERS[spell_type].ldam;
  1492.     else adj=0;
  1493.  return adj;
  1494. }
  1495.  
  1496. /* July 1995 - changed slightly (SK_level) for ALLOW_SKILLS - b.t. */
  1497.  
  1498. int SP_level_strength_adjust(object *op, int spell_type)
  1499. {  int adj;
  1500. #ifdef ALLOW_SKILLS
  1501.    int level=SK_level(op)+path_level_mod(op, spell_type);
  1502. #else
  1503.    int level=op->level+path_level_mod(op, spell_type);
  1504. #endif
  1505.     adj= (level-spells[spell_type].level);
  1506.     if(adj < 0) adj=0;
  1507.     if(SP_PARAMETERS[spell_type].ldur)
  1508.     adj/=SP_PARAMETERS[spell_type].ldur;
  1509.     else adj=0;
  1510.  return adj;
  1511. }
  1512.  
  1513. /*  The following function scales the spellpoint cost of
  1514. a spell by it's increased effectiveness.  Some of the
  1515. lower level spells become incredibly vicious at high
  1516. levels.  Very cheap mass destruction.  This function is
  1517. intended to keep the sp cost related to the effectiveness. */
  1518.  
  1519. /* July 1995 - changed slightly (SK_level) for ALLOW_SKILLS - b.t. */
  1520.  
  1521. int SP_level_spellpoint_cost(object *op, int spell_type)
  1522. {
  1523.   spell *s=find_spell(spell_type);
  1524. # ifdef ALLOW_SKILLS 
  1525.   int level=SK_level(op)+path_level_mod(op, spell_type);
  1526. #else
  1527.   int level=op->level+path_level_mod(op, spell_type);
  1528. #endif /* ALLOW_SKILLS */
  1529. #ifdef SPELLPOINT_LEVEL_DEPEND
  1530.   int sp;
  1531.   if(SP_PARAMETERS[spell_type].spl)
  1532.    sp= (int) (spells[spell_type].sp * 
  1533.            (1.0 + 
  1534.     (MAX(0,    (float)(level-spells[spell_type].level)/
  1535.     (float)SP_PARAMETERS[spell_type].spl ))));
  1536.   else sp= spells[spell_type].sp;
  1537.   sp *= PATH_SP_MULT(op,s);
  1538.   return MIN(sp,(spells[spell_type].sp + 50));
  1539. #else
  1540.   return s->sp*PATH_SP_MULT(op,s);
  1541. #endif /* SPELLPOINT_LEVEL_DEPEND */  
  1542. }
  1543.  
  1544.  
  1545.  
  1546. /*  move_swarm_spell:  peterm  */
  1547. /*  This is an implementation of the swarm spell.  It was written for
  1548. meteor swarm, but it could be used for any swarm.  A swarm spell
  1549. is a special type of object that casts swarms of other types
  1550. of spells.  Which spell it casts is flexible.  It fires the spells
  1551. from a set of squares surrounding the caster, in a given direction. */
  1552.  
  1553. void move_swarm_spell(object *op)
  1554. {  int x,y; int di;
  1555.     if(!(op->stats.hp--)||get_owner(op)==NULL) {
  1556.     remove_ob(op);
  1557.     free_object(op);
  1558.     return;
  1559.     }
  1560.    x=op->x; y=op->y;  /*  save original location of swarm object */
  1561.     
  1562.    if(op->stats.hp) di=RANDOM()%7-3;  /* get a random number of -3->3 */
  1563.     else di=0;  /* fire the last one from forward. */
  1564.    op->x+=freearr_x[absdir(op->direction +di)];
  1565.    op->y+=freearr_y[absdir(op->direction +di)];
  1566. /*  for level dependence, we need to know what spell is fired.  */
  1567. /*  that's stored in op->stats.sp  by fire_swarm  */
  1568.    if(!wall(op->map,op->x,op->y))
  1569.    fire_arch(op,op->direction,op->other_arch,op->stats.sp,0);
  1570.    op->x=x; op->y=y;  /* reset original location */
  1571.  
  1572. }
  1573.  
  1574. /*  fire_swarm:  peterm */
  1575. /*  The following routine creates a swarm of objects.  It actually
  1576.     sets up a specific swarm object, which then fires off all
  1577.     the parts of the swarm.  
  1578.  
  1579.   Interface:
  1580.     op:  the caster
  1581.     dir: the direction everything will be fired in
  1582.     swarm_type:  the archetype that will be fired
  1583.     spell_type:  the spell type of the archetype that's fired
  1584.     n:  the number to be fired.
  1585. */
  1586.     
  1587.  
  1588. void fire_swarm(object *op,int dir,archetype *swarm_type,int spell_type,int n)
  1589. {
  1590.   object *tmp;
  1591.   tmp=arch_to_object(find_archetype("swarm_spell"));
  1592.   tmp->x=op->x;
  1593.   tmp->y=op->y;        
  1594.   set_owner(tmp,op);       /* needed so that if swarm elements kill, caster gets xp.*/
  1595.   tmp->level=op->level;   /*needed later, to get level dep. right.*/
  1596.   tmp->stats.sp=spell_type;  /* needed later, see move_swarm_spell */
  1597.   tmp->stats.hp=n;        /* n in swarm*/
  1598.   tmp->other_arch=swarm_type;  /* the archetype of the things to be fired*/
  1599.   tmp->direction=dir; 
  1600.   tmp->invisible=1;
  1601.   insert_ob_in_map(tmp,op->map);
  1602. }
  1603.  
  1604.         
  1605. /*  look_up_spell_by_name:  peterm
  1606.     this function attempts to find the spell spname in spells[].
  1607.     if it doesn't exist, or if the op cannot cast that spname,
  1608.     -1 is returned.  */
  1609.  
  1610.  
  1611. int look_up_spell_by_name(object *op,char *spname) {
  1612.     int numknown;
  1613.     int spnum;
  1614.     int plen;
  1615.     int spellen;
  1616.     int i;
  1617.  
  1618.     if(spname==NULL) return -1;
  1619.     if(op==NULL) numknown=NROFREALSPELLS;
  1620.     else
  1621.     if(QUERY_FLAG(op, FLAG_WIZ)) numknown=NROFREALSPELLS;
  1622.         else numknown = op->contr->nrofknownspells;
  1623.     plen=strlen(spname);
  1624.     for(i=0;i<numknown;i++) {
  1625.     if(op==NULL) spnum=i;
  1626.     else
  1627.         if(QUERY_FLAG(op,FLAG_WIZ)) spnum=i;
  1628.         else  spnum = op->contr->known_spells[i];
  1629.  
  1630.     spellen=strlen(spells[spnum].name);
  1631.  
  1632.     if(strncmp(spname,spells[spnum].name,MIN(spellen,plen)) == 0 ) 
  1633.         return spnum;
  1634.     }
  1635.     return -1;
  1636. }
  1637.  
  1638.  
  1639.  
  1640. void put_a_monster(object *op,char *monstername) {
  1641.   object *tmp;
  1642.   archetype *at;
  1643.   int dir;
  1644.   int nx,ny;
  1645.   
  1646.   /* find a free square nearby */
  1647.   /* first we check the closest square for free squares */
  1648.   if((at=find_archetype(monstername))==NULL) return;
  1649.   dir=find_first_free_spot(at,op->map,op->x,op->y);
  1650.   if((tmp=arch_to_object(at))!=NULL) {
  1651.     nx=op->x+freearr_x[dir];
  1652.     ny=op->y+freearr_y[dir];
  1653.     tmp->x=nx;
  1654.     tmp->y=ny;
  1655.     tmp->map = op->map;
  1656.     insert_ob_in_map(tmp,op->map);
  1657.     /* thought it'd be cool to insert a burnout, too.*/
  1658.     tmp=get_archetype("burnout");
  1659.     tmp->map = op->map;
  1660.     tmp->x=nx;
  1661.     tmp->y=ny;
  1662.     insert_ob_in_map(tmp,op->map);
  1663.     }
  1664. }
  1665.  
  1666.  
  1667. /*  Some local definitions for shuffle-attack */
  1668. int color_array[20];
  1669. #define black 0
  1670. #define white 1
  1671. #define red 2
  1672. #define light_blue 3
  1673. #define blue 4
  1674. #define light_green 5
  1675. #define green 6
  1676. #define yellow 7
  1677. #define khaki 8
  1678.     struct {
  1679.     int attacktype;
  1680.     int face;
  1681.     int fg;
  1682.     int bg;
  1683.     } ATTACKS[22] = {
  1684.     {AT_PHYSICAL,0,0,12},
  1685.     {AT_PHYSICAL,0,0,12},  /*face = explosion*/
  1686.     {AT_PHYSICAL,0,0,12},
  1687.     {AT_MAGIC,1,1,12},
  1688.     {AT_MAGIC,1,1,12},   /* face = last-burnout */
  1689.     {AT_MAGIC,1,1,12},
  1690.     {AT_FIRE,2,3,12},
  1691.     {AT_FIRE,2,3,12},  /* face = fire....  */
  1692.     {AT_FIRE,2,3,12},
  1693.     {AT_ELECTRICITY,3,11,9},
  1694.     {AT_ELECTRICITY,3,11,9},  /* ball_lightning */
  1695.     {AT_ELECTRICITY,3,11,9},
  1696.     {AT_COLD,4,5,1},    
  1697.     {AT_COLD,4,5,1},  /* face=icestorm*/
  1698.     {AT_COLD,4,5,1},
  1699.     {AT_CONFUSION,5,0,12},
  1700.     {AT_POISON,7,0,12},
  1701.     {AT_POISON,7,0,12}, /* face = acid sphere.  generator */
  1702.     {AT_POISON,7,8,12},  /* poisoncloud face */
  1703.     {AT_SLOW,8,0,12},
  1704.     {AT_PARALYZE,9,11,9},
  1705.     {AT_FEAR,10,0,12}  };
  1706.  
  1707.  
  1708.  
  1709. /*  shuffle_attack:  peterm */
  1710. /*  This routine shuffles the attack of op to one of the 
  1711.    ones in the list.  It does this at random.  It also
  1712.    chooses a face appropriate to the attack that is
  1713.    being committed by that square at the moment.  
  1714.     right now it's being used by color spray and create pool of
  1715.     chaos.  */
  1716.  
  1717. void shuffle_attack(object *op,int change_face)
  1718. {
  1719.     int i;
  1720.     i=RANDOM()%22;
  1721.     op->attacktype|=ATTACKS[i].attacktype|AT_MAGIC;
  1722.     if(change_face) {
  1723.     op->face=&new_faces[op->arch->faces[ATTACKS[i].face]];
  1724. #if 0
  1725.     op->face.fg=ATTACKS[i].fg;
  1726.     op->face.bg=ATTACKS[i].bg;
  1727. #endif
  1728.     }
  1729. }
  1730.  
  1731.  
  1732. /*  the following function reads from the file 'spell_params' in    
  1733. the lib dir, and resets the array in memory to reflect the values
  1734. in spell_parameters.  The format in there MUST be:
  1735. spell name
  1736. spell_number bdam bdur ldam ldur
  1737.  for
  1738. base damage of spell, base duration of spell, level-dependency for damage
  1739. level-dependency for duration--examples
  1740. magic bullet
  1741. 0 0 0 0
  1742. large icestorm
  1743. 0 1 1 1
  1744. small fireball
  1745. 1 0 0 8
  1746. ....
  1747.  
  1748. The parameters have different effects for different spells.
  1749. Please refer to the documentation.
  1750. */
  1751. void init_spell_param()
  1752. {
  1753.   FILE *spell_params;
  1754.   char fname[MAX_BUF];
  1755.   char spell_name[50];
  1756.   char spell_attrib[50];
  1757.   int bdam,bdur,ldam,ldur;
  1758.   int sp;
  1759.   int level;
  1760.   int spellindex;
  1761.   int spl;  /*  the spellpoint level dependency */
  1762.  
  1763.   /* This is hokey, but this function gets called everytime.
  1764.   I need these colors for shuffle-attack to work right, and
  1765.   they seem to change form implementation to implemention of
  1766.   crossfire.  So I'm making my own array here for use in
  1767.   shuffle-attack. it's global in scope to this file.*/
  1768.   
  1769.   color_array[black]=find_color("black");
  1770.   color_array[white]=find_color("white");
  1771.   color_array[red]=find_color("red");
  1772.   color_array[light_blue]=find_color("light_blue");
  1773.   color_array[blue]=find_color("blue");
  1774.   color_array[light_green]=find_color("light_green");
  1775.   color_array[green]=find_color("green");
  1776.   color_array[yellow]=find_color("yellow");
  1777.   color_array[khaki]=find_color("khaki");
  1778.  
  1779.   /*explosion--for physical*/
  1780.   ATTACKS[0].fg=color_array[black];
  1781.   ATTACKS[0].bg=color_array[khaki];
  1782.   ATTACKS[1].fg=color_array[black];
  1783.   ATTACKS[1].bg=color_array[khaki];
  1784.   ATTACKS[2].fg=color_array[black];
  1785.   ATTACKS[2].bg=color_array[khaki];  
  1786.   /*magic--burnout attack */
  1787.   ATTACKS[3].fg=color_array[light_blue];
  1788.   ATTACKS[3].bg=color_array[khaki];
  1789.   ATTACKS[4].fg=color_array[light_blue];
  1790.   ATTACKS[4].bg=color_array[khaki];
  1791.   ATTACKS[5].fg=color_array[light_blue];
  1792.   ATTACKS[5].bg=color_array[khaki];  
  1793.   /*fire--for fire*/
  1794.   ATTACKS[6].fg=color_array[red];
  1795.   ATTACKS[6].bg=color_array[khaki];
  1796.   ATTACKS[7].fg=color_array[red];
  1797.   ATTACKS[7].bg=color_array[khaki];
  1798.   ATTACKS[8].fg=color_array[red];
  1799.   ATTACKS[8].bg=color_array[khaki];  
  1800.   /*electricity--ball lightning face */
  1801.   ATTACKS[9].fg=color_array[yellow];
  1802.   ATTACKS[9].bg=color_array[khaki];
  1803.   ATTACKS[10].fg=color_array[yellow];
  1804.   ATTACKS[10].bg=color_array[khaki];
  1805.   ATTACKS[11].fg=color_array[yellow];
  1806.   ATTACKS[11].bg=color_array[khaki];  
  1807.   /*icestorm--for cold*/
  1808.   ATTACKS[12].fg=color_array[light_blue];
  1809.   ATTACKS[12].bg=color_array[white];
  1810.   ATTACKS[13].fg=color_array[light_blue];
  1811.   ATTACKS[13].bg=color_array[white];
  1812.   ATTACKS[14].fg=color_array[light_blue];
  1813.   ATTACKS[14].bg=color_array[white];
  1814.   /* madness--madness*/
  1815.   ATTACKS[15].fg=color_array[black];
  1816.   ATTACKS[15].bg=color_array[khaki];
  1817.  
  1818.   /* poison --  poisoncloud */
  1819.   ATTACKS[16].fg=color_array[white];
  1820.   ATTACKS[16].bg=color_array[light_green];
  1821.   ATTACKS[17].fg=color_array[white];
  1822.   ATTACKS[17].bg=color_array[light_green];
  1823.   ATTACKS[18].fg=color_array[white];
  1824.   ATTACKS[18].bg=color_array[light_green];
  1825.   
  1826.  
  1827.   /*  slow */
  1828.   
  1829.   ATTACKS[19].fg=color_array[black];
  1830.   ATTACKS[19].bg=color_array[khaki];
  1831.   /* paralize -- stars */
  1832.   ATTACKS[20].fg=color_array[yellow];
  1833.   ATTACKS[20].bg=color_array[khaki];  
  1834.   /* fear */
  1835.  
  1836.   ATTACKS[21].fg=color_array[black];
  1837.   ATTACKS[21].bg=color_array[khaki];  
  1838.  
  1839.   sprintf(fname,"%s/%s",LibDir,"spell_params");
  1840.   if(! (spell_params=fopen(fname,"r")))
  1841.     {
  1842.     perror(fname);
  1843.     return;
  1844.     }
  1845.     
  1846.   while(!feof(spell_params))
  1847.     {
  1848.     fgets(spell_name,49,spell_params);
  1849.     spellindex=look_up_spell_by_name(NULL,spell_name);
  1850.     if(spellindex==-1) {
  1851.         fprintf(stderr,"\nUnrecognized spell: %s",spell_name);
  1852.         continue;
  1853.     }
  1854.     fgets(spell_attrib,49,spell_params);
  1855.     sscanf(spell_attrib,"%d %d %d %d %d %d %d",&level,&sp,&bdam,&bdur,&ldam,&ldur,&spl);
  1856.     spells[spellindex].sp=sp;
  1857.     spells[spellindex].level=level;
  1858.     SP_PARAMETERS[spellindex].bdam=bdam;
  1859.     SP_PARAMETERS[spellindex].bdur=bdur;
  1860.         SP_PARAMETERS[spellindex].ldam=ldam;
  1861.         SP_PARAMETERS[spellindex].ldur=ldur;
  1862.     SP_PARAMETERS[spellindex].spl=spl;
  1863.     }
  1864. }
  1865.  
  1866. /* get_pointed_target() - this is used by finger of death
  1867.  * and the 'smite' spells. Returns the pointer to the first
  1868.  * monster in the direction which is pointed to by op. b.t.
  1869.  */
  1870.  
  1871. object *get_pointed_target(object *op, int dir) {
  1872.   object *target;
  1873.   int x,y;
  1874.  
  1875.   if (dir==0) return NULL;
  1876.   for(x=op->x+freearr_x[dir],y=op->y+freearr_y[dir]
  1877.      ;!out_of_map(op->map,x,y)&&!blocks_view(op->map,x,y)
  1878.      &&!wall(op->map,x,y);x+=freearr_x[dir],y+=freearr_y[dir])
  1879.         for(target=get_map_ob(op->map,x,y);target;target=target->above) {
  1880.               if(target==NULL) break;
  1881.               if(QUERY_FLAG(target,FLAG_MONSTER))
  1882.                    if(!blocks_magic(op->map,x,y))
  1883.                           return target;
  1884.                    else break;
  1885.         }
  1886.  
  1887.   return ((object *) NULL);
  1888. }
  1889.  
  1890. /* cast_smite_arch() - the priest points to a creature and causes
  1891.  * a 'godly curse' to decend. I generalized this a bit so that several
  1892.  * spells will be possible to use w/ this code (eg fire_arch, cast_cone).
  1893.  * -b.t.
  1894.  */
  1895.  
  1896. int cast_smite_spell (object *op, int dir, int type) {
  1897.    object *effect, *target = get_pointed_target(op,dir);
  1898. #ifdef MULTIPLE_GODS
  1899.    int godnr = get_god(op);
  1900. #endif
  1901.  
  1902.    if(!target
  1903. #ifdef MULTIPLE_GODS /* if we don't worship a god, or target a creature
  1904.                       * of our god, the spell will fail.  */
  1905.       || godnr ==-1
  1906.       ||(target->title&&godnr==(get_god(target)))
  1907.       ||(target->race&&strstr(target->race,Gods[godnr].aligned_race))
  1908. #endif
  1909.    ) {
  1910.         new_draw_info(NDI_UNIQUE,0,op,"Your request is unheeded.");
  1911.         return 0;
  1912.    }
  1913.  
  1914.    if (spellarch[type] != (archetype *) NULL)
  1915.       effect = arch_to_object(spellarch[type]);
  1916.    else
  1917.       return 0;
  1918.  
  1919.   /* tailor the effect by priest level and worshipped God */
  1920.    effect->level=SK_level(op);
  1921. #ifdef MULTIPLE_GODS
  1922.    if(effect->attacktype&AT_HOLYWORD||effect->attacktype&AT_GODPOWER)
  1923.         if(tailor_god_spell(effect,op,godnr))
  1924.            new_draw_info_format(NDI_UNIQUE,0,op,
  1925.                 "%s answers your call!",determine_god(op));
  1926.         else {
  1927.            new_draw_info(NDI_UNIQUE,0,op,"Your request is ignored.");
  1928.            return 0;
  1929.         }
  1930. #endif 
  1931.  
  1932.    /* size of the area of destruction */
  1933.    effect->stats.hp=SP_PARAMETERS[type].bdur +
  1934.                 SP_level_strength_adjust(op,type);
  1935.    /* how much woe to inflict :) */
  1936.    effect->stats.dam=SP_PARAMETERS[type].bdam +
  1937.                 SP_level_dam_adjust(op,type);
  1938.    if(effect->stats.dam<0) effect->stats.dam = 127;
  1939.    effect->stats.maxhp=effect->count; /*??*/
  1940.    set_owner(effect,op);
  1941.  
  1942.    /* ok, tell it where to be, and insert! */
  1943.    effect->x=target->x;effect->y=target->y;
  1944.    insert_ob_in_map(effect,op->map);
  1945.  
  1946.    return 1;
  1947. }
  1948.  
  1949.